package lex.mxbeans.ui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.lex.swing.ContainerFactory;

import lex.mxbeans.utils.MXBeansUtils;

public class MXBeanViewPane extends JPanel
{
	private JToolBar toolBar;
	private JLabel mxbeanClass;
	private JSplitPane splitPane;
	private ObjectInspectorPane inspectorPane;
	private List<MXBeanTable> tables = null;

	public MXBeanViewPane()
	{
		super();
		this.tables = new ArrayList<MXBeanTable>();
		Timer timer = new Timer( 500, null );
		timer.addActionListener( new ActionListener(){
			@Override
			public void actionPerformed( ActionEvent e )
			{
				for( MXBeanTable t : tables )
					t.reload();
			}
		} );
		timer.start();
		initialize();
	}

	public void setMXBeans( final Object[] beans )
	{
		int n = beans.length;
		if( 0 == n )
			return;
		JComponent top = null;
		if( 1 == n )
		{
			top = new JScrollPane( this.createMXBeanTable( beans[0] ) );
		}
		else
		{
			final JTabbedPane tab = ContainerFactory.createCloseTabPane();
			for( int i = 0; i < n; i++ )
				tab.addTab( Integer.toString( i ), new JScrollPane( this
					.createMXBeanTable( beans[i] ) ) );
			top = tab;
		}
		this.mxbeanClass.setText( getClassName( beans[0] ) );
		this.getSplitPane().setTopComponent( top );
	}

	private static String getClassName( Object bean )
	{
		Class<?> clz = MXBeansUtils.findSuperClass( bean.getClass() );
		if( null == clz )
			clz = bean.getClass();
		String name = clz.getCanonicalName();
		if( null == name )
			name = clz.getName();
		return name;
	}

	private static class MXBeanTable extends JTable
	{
		private MXBeanTableModel model = null;

		public MXBeanTable( Object bean )
		{
			model = new MXBeanTableModel( bean );
			this.setModel( model );
			this.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
			this.setAutoCreateRowSorter( true );
			this.getColumnModel().getColumn( 0 ).setPreferredWidth( 200 );
			this.getColumnModel().getColumn( 1 ).setPreferredWidth( 350 );
			this.getSelectionModel().setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
		}

		public void reload()
		{
			int index = this.getSelectedRow();
			model.reload();
			if( -1 != index )
				this.getSelectionModel().setSelectionInterval( index, index );
		}

		public Object getSelectedValue()
		{
			int index = this.getSelectedRow();
			Object obj = null;
			if( -1 != index )
				obj = model.getValue( this.convertRowIndexToModel( index ) );
			return obj;
		}
	}

	private JTable createMXBeanTable( Object bean )
	{
		final MXBeanTable table = new MXBeanTable( bean );
		this.tables.add( table );
		table.getSelectionModel().addListSelectionListener( new ListSelectionListener(){
			@Override
			public void valueChanged( ListSelectionEvent e )
			{
				getInspectorPane().setObject( table.getSelectedValue() );
			}
		} );
		return table;
	}

	private void initialize()
	{
		setLayout( new BorderLayout() );
		add( getToolBar(), BorderLayout.NORTH );
		add( this.getSplitPane(), BorderLayout.CENTER );
	}

	private JSplitPane getSplitPane()
	{
		if( null == splitPane )
		{
			splitPane = ContainerFactory.createBorderlessSplitPane();
			splitPane.setName( getClass().getName() + ".split" );
			splitPane.setOrientation( JSplitPane.VERTICAL_SPLIT );
			splitPane.setBottomComponent( this.getInspectorPane() );
			splitPane.setResizeWeight( 0.75D );
		}
		return splitPane;
	}

	private ObjectInspectorPane getInspectorPane()
	{
		if( null == this.inspectorPane )
			this.inspectorPane = new ObjectInspectorPane();
		return inspectorPane;
	}

	private JToolBar getToolBar()
	{
		if( toolBar == null )
		{
			toolBar = new JToolBar();
			toolBar.add( getMxbeanClass() );
		}
		return toolBar;
	}

	private JLabel getMxbeanClass()
	{
		if( mxbeanClass == null )
		{
			mxbeanClass = new JLabel();
		}
		return mxbeanClass;
	}
}
